package game_frame

import (
	"gamesdk/common/log"
	"sync"
	"sync/atomic"
)

type TraverseUserFunc func(value *User) bool

type UserManager struct {
	count        int32
	offline      int32
	users        sync.Map //在线用户管理
	offlineUsers sync.Map // 离线用户池
	usersPool    sync.Map //用户池
	waitGroup    *sync.WaitGroup
}

//添加用户
func (this *UserManager) Add(user *User) {
	defer log.Trace()()
	this.users.Store(user.GetId(), user)
	atomic.AddInt32(&this.count, 1)
	this.waitGroup.Add(1)
}

func (this *UserManager) GetOnlineAndOfflineNum() {
	// go func() {
	// 	for {
	// 		log.Info("在线人数:%d", atomic.LoadInt32(&this.count))
	// 		log.Info("托管人数:%d", atomic.LoadInt32(&this.offline))
	// 		time.Sleep(time.Second * 5)
	// 	}
	// }()
}

//删除用户
func (this *UserManager) DeleteById(id int64) {
	defer log.Trace()()
	user := this.GetById(id)
	if user != nil {
		this.users.Delete(id)
		atomic.AddInt32(&this.count, -1)
		this.waitGroup.Done()
		//runtime.GC()
	}

}

//添加离线用户
func (this *UserManager) AddOffline(user *User) {
	defer log.Trace()()
	this.offlineUsers.Store(user.GetId(), user)
	atomic.AddInt32(&this.offline, 1)
	this.waitGroup.Add(1)
}

//删除离线用户
func (this *UserManager) DeleteOfflineById(id int64) {
	defer log.Trace()()
	user := this.GetOfflineById(id)
	if user != nil {
		this.offlineUsers.Delete(id)
		atomic.AddInt32(&this.offline, -1)
		this.waitGroup.Done()
		//runtime.GC()
	}

}

//获取离线用户
func (this *UserManager) GetOfflineById(id int64) *User {
	defer log.Trace()()
	u, ok := this.offlineUsers.Load(id)
	if !ok {
		return nil
	}
	user, ok := u.(*User)
	if !ok {
		log.Warn("vli no this *User")
		return nil
	}
	return user
}

//获取用户
func (this *UserManager) GetById(id int64) *User {
	defer log.Trace()()
	u, ok := this.users.Load(id)
	if !ok {
		return nil
	}
	user, ok := u.(*User)
	if !ok {
		log.Warn("vli no this *User")
		return nil
	}
	return user
}

/*
*遍历所有用户
 */
func (this *UserManager) Traverse(f TraverseUserFunc) {
	defer log.Trace()()
	function := func(key, value interface{}) bool {
		if value != nil {
			user, ok := value.(*User)
			if !ok {
				log.Warn("user is not *User")
			} else {
				return f(user)
			}
		}
		return true
	}
	this.users.Range(function)
}
